/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Controller;

import Controller.XML.MessagesXMLLocal;
import agh.rozproszony.messages.MessagesRMIServer;
import agh.rozproszony.messages.MessagesServer;
import agh.rozproszony.model.Message;
import agh.rozproszony.model.User;
import java.io.*;
import java.rmi.RemoteException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *  Statusy wiadomości 1 - przeczytama/wysłana; 2 - nieprzeczytana; 3 - nie wysłana
 * Wektory 0 - moj wektor; 1 - suma tamtych;
 * @author Seweryn
 */
public class MessagesController {
    private final MessagesServer server;
    private final MessagesXMLLocal xml;
    private Map<Integer, Integer> wektory;
    private User user;
    private File LogWek;
    protected BufferedWriter o;
    private static MessagesController instance = null;
    
    
    protected MessagesController(MessagesServer pmSerwer, User pmUser)
    {
        server = pmSerwer;
        wektory = new HashMap<Integer, Integer>();
        user = pmUser;
        xml = new MessagesXMLLocal("wiadomosci.xml");

        LogWek = new File("wektorClient1.txt");
        FileWriter file = null;
        try {
            file = new FileWriter(LogWek, true);
        } catch (IOException ex) {
            Logger.getLogger(MessagesRMIServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        o = new BufferedWriter(file);
        wektory.put(user.getId(), 0);
        try {
            if(server.getWektor().containsKey(user.getId()) ==false)
            {
                server.addWektor(user.getId());
                
            }
        } catch (RemoteException ex) {
            Logger.getLogger(MessagesController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
   public static MessagesController getInstance(MessagesServer pmSerwer, User pmUser) {
      if(instance == null) {
         instance = new MessagesController(pmSerwer, pmUser);
      }
      return instance;
   }
    @Override
    protected void finalize() throws Throwable
    {
        o.close();
        super.finalize();
        
        
    }
     public Message getMessage(int messageId)
     {
         Message lvMes;
         lvMes = xml.getMessage(messageId);
         if(lvMes == null)
         {
            try {
                lvMes = server.getMessage(messageId);
                xml.InsertMessage(lvMes);
             } catch (RemoteException ex) {
                 System.out.println("ERROR:MessagesController->insertMessage(): " + ex.toString());
                 return null;
             }
         }
         return lvMes;
     }
     

     public List<Message> getNotReadedMessages(int userId)
     {
         checkWektor();
         return xml.getNotReadedMessages();
     }
     public List<Message> getAllMessages(int userId)
     {
         List<Message> lvMes = null;
            try {
                Map<Integer, Integer> lvWektor = server.getWektor();
                lvMes = server.getMessages(userId);
                xml.resetXML();
                xml.InsertMessage(lvMes);
                wektory = lvWektor;
                LogujWektor();
             } catch (RemoteException ex) {
                 System.out.println("ERROR:MessagesXMLLocal->insertMessage(): " + ex.toString());
                 return null;
             }
         return lvMes;  
    }
    

    public Boolean insertMessage(Message message) 
    {
        Collection<Integer> lvCol = wektory.values();
        int s = 0;
        for(int i:lvCol)s+=i;
        message.setRecipientId(s);
        try {
            server.insertMessage(message);
            
        } catch (RemoteException ex) {
            System.out.println("ERROR:MessagesController->insertMessage(): " + ex.toString());
            xml.InsertMessage(message,3);
            return false;
        }
        xml.InsertMessage(message,1);
        addWektor();
        LogujWektor();
        return true;
    }
    /**
     * Funkcja która w zależności od wartości wektora na serwerze i u klienta wysyła zaległe wiadomości bądź aktualizuje obecne
     * powinna być uruchamiana przy każdym włączeniu programu.
     * @return Zwraca true jeśli nastąpiła jakaś zmiana lub false jeśli nic się nie stało.
     */
    public Boolean checkWektor()
    {
        Boolean lvChanged = false;
        try {
            Map<Integer, Integer> lvWektor = server.getWektor();
            if(wiekszyWektor()==2)
            {
                lvChanged=true;
                List<Message> lvM = xml.getNotSendMessages();
                for(Message m:lvM)
                {
                    server.insertMessage(m);
                    xml.changeStatus(m.getId(), 1);
                    server.addWektor(user.getId());
                    
                }
                
                
            }
            if(wiekszyWektor()==1)
            {
                lvChanged = true;
                getAllMessages(user.getId());
            }
            
        } catch (RemoteException ex) {
            System.out.println("ERROR:MessagesController->check wektor(): " + ex.toString());
        }
        return lvChanged;
    }
    /**
     * Umożliwia zmianę statusu wiadomosci;
     * @param pmMessageId
     * @param pmStatus
     * @return 
     */
    public Boolean changeStatus(int pmMessageId, int pmStatus)
    {
        xml.changeStatus(pmStatus, pmStatus);
        return true;
    }
    /**
     * Ustawia wiadomosć jako przeczytaną;
     * @param pmMessageId
     * @return 
     */
    public Boolean setReaded(int pmMessageId)
    {
        return changeStatus(pmMessageId, 2);
    }
     public List<Message> getLastMessages(int numberOfMessages)
     {
         List<Message> lvMes = null;
                checkWektor();
                lvMes = xml.getLastMessages(numberOfMessages);
         return lvMes;  
    }
     private void LogujWektor()
     {

        try {

            Set<Integer> a = wektory.keySet();
            Date czas = new Date();
            o.write(czas.toGMTString()+" :stan wektora User:");
            o.newLine();
            for(Integer m:a)
            {
                
              o.write("User: "+m+" wartosc: "+Integer.toString(wektory.get(m))+"\n");
              o.newLine();
            }
            o.flush();
            
        } catch (IOException ex) {
            System.out.println("ERROR:MessagesController->LogujWektor(): " + ex.toString());
        }
    
     }
     private Boolean addWektor()
     {
        try {
            server.addWektor(user.getId());
            wektory.put(user.getId(), wektory.get(user.getId())+1);
        } catch (RemoteException ex) {
            System.out.println("ERROR:MessagesController->addWektor(): " + ex.toString());
            return false;
        }
        return true;
     }
     private int wiekszyWektor()
    {
        Collection<Integer> lvCol = wektory.keySet();
        Map<Integer, Integer> m = null;
        try {
            m = server.getWektor();
        } catch (RemoteException ex) {
            System.out.println("ERROR:MessagesController->wiekszyWektor(): " + ex.toString());
            return 0;
        }
        int lvSuma = 0;
        int lvRoz = 0;
        for (int i : lvCol) {
            if (m.containsKey(i) && wektory.containsKey(i)) {
                if (m.get(i) > wektory.get(i)) {
                    lvSuma++;
                } else if (m.get(i) < wektory.get(i)) {
                    lvRoz++;
                }
            }
        }
        if (lvSuma > 0 && lvRoz == 0) {
            return 1;
        }
        if (lvRoz > 0) {
            return 2;
        }
        return 0;
    }
              
}
